package org.bigjava.novelplatform.common.config;

import cn.hutool.core.io.FileUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.bigjava.novelplatform.common.constant.ComplexConstant;
import org.bigjava.novelplatform.common.formatters.DateConverter;
import org.bigjava.novelplatform.common.formatters.ToCodeMesEnum;
import org.bigjava.novelplatform.common.handlerInterceptor.AdminHandlerInterceptor;
import org.bigjava.novelplatform.common.handlerInterceptor.IdentificationInterceptor;
import org.bigjava.novelplatform.common.handlerInterceptor.WriterHandlerInterceptor;
import org.bigjava.novelplatform.common.utils.StringUtils;
import org.bigjava.novelplatform.common.web.listener.SessionListener;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.log.LogFormatUtils;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.util.UrlPathHelper;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.List;

import static org.bigjava.novelplatform.common.constant.NovelInfoConstant.*;


/**
 * @author ykh
 * @create 2022-03-20 9:44
 */
@Slf4j
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Value("${novel.web.resourcePath:}")
    String resourcePath;



    //https://blog.csdn.net/ngl272/article/details/122458262
    //使用配置spring.mvc.pathmatch.matching-strategy=ant-path-matcher，或如下
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper helper = new UrlPathHelper();
        /*
         * 由于 SpringMVC从2.6.0版本起采用PathPatternParser作为默认路径匹配策略
         * 在使用PathPatternParser 后，现在传进来的url是原始的未decode过的url
         * ，但是UrlPathHelper 默认设置是decodeURL的，
         * 这就导致重复进行了一次encode
         */
        helper.setUrlDecode(false);
        helper.setDefaultEncoding(StandardCharsets.UTF_8.name());
        configurer.setUrlPathHelper(helper);
    }



//    @SneakyThrows
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        if (StringUtils.isEmpty(resourcePath)) {
            resourcePath = ComplexConstant.RESOURCE_PATH;
        }
        resourcePath = resourcePath.replaceAll("/", File.separator);
        final File file = new File(resourcePath);
        if (!file.isAbsolute()) {
            throw new IllegalArgumentException("资源路径必须是绝对路径");
        }
        //创建文件
        FileUtil.mkdir(file);
        FileUtil.mkdir(new File(USER_HEAD_DISK_PATH));
        FileUtil.mkdir(new File(BOOK_COVER_DISK_PATH));
        FileUtil.mkdir(new File(EXTENSION_DISK_PATH));
        URI resourceUri = file.toURI();
        String diskPath = null;
        try {
            diskPath = resourceUri.toURL().toString();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        String urlMatch = MAP_RESOURCE_PATH+"/**";
        log.info("{} 映射资源到 {}", urlMatch, diskPath);
        registry.addResourceHandler(urlMatch).addResourceLocations(diskPath);
    }

    /**
     * 跨域，或者使用注解@CrossOrigin配置
     *
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                //是否发送Cookie
                .allowCredentials(true)
                //设置放行哪些原始域   SpringBoot2.4.4下低版本使用.allowedOrigins("*")
//                .allowedOriginPatterns("*")
                .allowedOriginPatterns("http://localhost:8080", "http://127.0.0.1:8080")
                //放行哪些请求方式
//                .allowedMethods("GET", "POST", "PUT", "DELETE")
                //或者放行全部
                .allowedMethods("*")
                //放行哪些原始请求头部信息
                .allowedHeaders("*")
                //暴露哪些原始请求头部信息
                .exposedHeaders("*")
                .maxAge(3600);
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {

    }

    /**
     * 拦截器配置
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //身份认证拦截器
        registry.addInterceptor(new IdentificationInterceptor())
                .addPathPatterns("/api/user/**")
                .addPathPatterns("/api/writer/**")
        .addPathPatterns("/api/order/**");
        registry.addInterceptor(new WriterHandlerInterceptor())
                .addPathPatterns("/api/writer/**");
//        registry.addInterceptor(new AdminHandlerInterceptor())
//                .addPathPatterns("/api/admin/**");
    }


    /**
     * 类型转换器，格式转换器
     *
     * @param registry
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverterFactory(new ToCodeMesEnum());
        registry.addConverter(new DateConverter());
    }


    @Bean
    public ServletListenerRegistrationBean configContextListener() {
        ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean();
        bean.setListener(new SessionListener());
        return bean;
    }
}
